package com.polaris.live.ui.message.fragment

import android.os.Bundle
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.StringUtils
import com.polaris.live.R
import com.polaris.live.adapter.MessageAdapter
import com.polaris.live.adapter.MessageHeadAdapter
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.mvvm.base2.BaseVbFragment
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.DebounceHelper
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.NavigationBarUtils
import com.polaris.live.common.util.SystemUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.ViewUtils
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.UserConst
import com.polaris.live.databinding.FragmentMessageSingleBinding
import com.polaris.live.dialog.common.ConfirmCanalDetailDialog
import com.polaris.live.im.db.entity.GreetMessageEntity
import com.polaris.live.im.manager.ImMessageManager
import com.polaris.live.im.sfs.COMMAND_STRANGER_MESSAGE
import com.polaris.live.im.sfs.COMMAND_SYSTEM_MESSAGE
import com.polaris.live.im.sfs.EXT_FLAG_PUSH_MESSAGE
import com.polaris.live.im.sfs.SYSTEM_USER_ID
import com.polaris.live.im.sfs.TYPE_MESSAGE_CALL
import com.polaris.live.im.sfs.TYPE_MESSAGE_IMAGE
import com.polaris.live.im.sfs.TYPE_MESSAGE_INVITATION_ROOM
import com.polaris.live.im.utils.MessageEntityUtils
import com.polaris.live.im.utils.toMessageEntity
import com.polaris.live.manager.LiveStateManager
import com.polaris.live.resp.back_resp.InfoOtherResp
import com.polaris.live.translation.R.string
import com.polaris.live.ui.message.widget.single_message.MessageSystemTextItemHolder
import com.polaris.live.ui.message.widget.single_message.MessageTextItemHolder
import com.polaris.live.ui.party.PartyUserStateUtil
import com.polaris.live.ui.party.activity.PartyAnchorActivity
import com.polaris.live.utils.BitwiseUtils
import com.polaris.live.utils.CommonUtils.toBoolean
import com.polaris.live.utils.LiveUtils
import com.polaris.live.utils.RecyclerUtils.getFirstPosition
import com.polaris.live.utils.RecyclerUtils.getLastPosition
import com.polaris.live.utils.StartCallProxy
import com.polaris.live.utils.WebUtils
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.utils.photo.PicturePreview
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.utils.route.RouterUtils
import com.polaris.live.utils.state.getDisplayPosition
import com.polaris.live.viewmodel.message.MessageViewModel

/**
 * MessageSingleFragment
 *
 * @author Created by lucas on 2023/10/28 09:46
 */
class MessageSingleFragment : BaseVbFragment<MessageViewModel, FragmentMessageSingleBinding>() {

    private var mScrollState = RecyclerView.SCROLL_STATE_IDLE
    private var mIsInitData = true
    private var mIsPullLoadEnable = false
    private var mIsLoading = false

    private val mOtherId by lazy { arguments?.getLong("otherId", 0) ?: 0 }
    private val mAvatar by lazy { arguments?.getString("avatar") }
    private val mAvatarFrame by lazy { arguments?.getString("avatarFrame") }
    private val mChatBubble by lazy { arguments?.getString("chatBubble") }
    private val mNestedPage by lazy { arguments?.getBoolean("nestedPage", false) ?: false }
    private val mNeedClickAvatar by lazy {
        arguments?.getBoolean(
            LiveConst.Params.NEED_CLICK_AVATAR,
            true
        ) ?: true
    }

    private val mAdapter by lazy { MessageAdapter(mOtherId) }
    private val mHeadAdapter by lazy { MessageHeadAdapter() }

    private var mUser: InfoOtherResp? = null
    private var mConcatAdapter: ConcatAdapter? = null
    private var mOnSetStateNormal: (() -> Unit)? = null

    //是否有过打招呼消息
    private var mGreetMessage: GreetMessageEntity? = null

    override fun initView(savedInstanceState: Bundle?) {
        initView()
        initObserver()
        initListener()
        initDataFragment()
        mViewModel.getGreetMessage(mOtherId)
    }

    private fun initView() {
        //嵌套系统页面需要做特殊处理
        if (mNestedPage && mOtherId == SYSTEM_USER_ID) {
            NavigationBarUtils.setNavigationHeightIfTransparent(mBinding.recycler)
        }
        mConcatAdapter = ConcatAdapter(mAdapter)
        mBinding.recycler.apply {
            layoutManager = LinearLayoutManager(requireContext()).apply {
                reverseLayout = true
                stackFromEnd = true
            }
            itemAnimator = null
            adapter = mConcatAdapter
        }
    }

    private fun initObserver() {

        setAvatar(mAvatar, mAvatarFrame, mChatBubble)

        //检查自己封面照是否在审核
        mViewModel.userCoverLiveData.observe(this) { resultState ->
            parseState(resultState, {
                val isAuditing =
                    it.status == AppConst.CoverPhoto.UNDER_REVIEW || it.status == AppConst.CoverPhoto.REVIEWING
                if (isAuditing) {
                    ToastGravity.showGravity(StringUtils.getString(string.cover_auditing))
                    return@parseState
                }

                val isGoImage =
                    it.status == null || it.status == AppConst.CoverPhoto.APPROVED || it.status == AppConst.CoverPhoto.REVIEW_NOT
                if (it.allowedUpload && isGoImage) {
                    Router.builder(RoutePath.SET_LIVE_IMAGE_ACTIVITY)
                        .withInt("type", LiveConst.Type.CLIENT_DEFAULT)
                        .withString("name", "")
                        .navigation(requireActivity())
                } else {
                    Router.builder(RoutePath.SET_COVER_ACTIVITY).navigation(requireActivity())
                    ToastGravity.showGravity(string.more_than_twice)
                }
            }, {})
        }
        //获取更多消息
        mViewModel.messageLiveData.observe(this) {
            if (mIsInitData) {
                mAdapter.addData(it)
                mIsInitData = false
                mIsPullLoadEnable = true
                scrollToBottom()
                mBinding.recycler.post { getSayHiMessage() }
            } else {
                mAdapter.addData(it)

                mIsLoading = false
            }
        }

        ImMessageManager.observeSingleUserId(this, mOtherId)
        ImMessageManager.observeReceive(this) {
            if (it.getOtherId() != mOtherId) {
                return@observeReceive
            }
            mAdapter.addData(0, it.toMessageEntity())

            if (isToBottom()) {
                scrollToBottom()
            }
        }
        ImMessageManager.observeSend(this) { _, message ->
            if (message.recipient != mOtherId) {
                return@observeSend
            }
            val position = mAdapter.data.indexOfLast { it.msgId == message.msgId }
            if (position != -1) {
                mAdapter.setData(position, message)
            } else {
                mAdapter.addData(0, message)
                scrollToBottom()
            }
        }
        mViewModel.greetMessageLiveData.observe(this) {
            mGreetMessage = it
        }
        mViewModel.inviteJoinPrepareLiveData.observe(this) { resultState ->
            parseState(resultState, {
                when (it.liveType) {
                    LiveConst.Type.PARTY_GAME_LIVE -> {
                        Router.instance.setPath(RoutePath.PARTY_GAME_SPECTATOR_ACTIVITY)
                            .withLong(LiveConst.Params.ANCHORID, it.anchorId)
                            .withInt(LiveConst.Params.LIVETYPE, it.liveType)
                            .withString(LiveConst.Params.ROOMID, it.roomId ?: "${it.anchorId}")
                            .navigation(requireContext())
                    }

                    LiveConst.Type.PARTY_LIVE, LiveConst.Type.VIDEO_PARTY -> {
                        Router.instance.setPath(RoutePath.PARTY_SPECTATOR_ACTIVITY)
                            .withLong(LiveConst.Params.ANCHORID, it.anchorId)
                            .withInt(LiveConst.Params.LIVETYPE, it.liveType)
                            .withString(LiveConst.Params.ROOMID, it.roomId ?: "${it.anchorId}")
                            .navigation(requireContext())
                    }

                    LiveConst.Type.LIVE_AND_MATCH, LiveConst.Type.ONLY_LIVE -> {
                        val setting = UserManager.getUser().setting?.liveSwitch
                        if (setting != null && !setting.toBoolean()) {
                            ConfirmCanalDetailDialog.show(
                                requireContext(),
                                mTitle = StringUtils.getString(string.prompt),
                                mDetail = StringUtils.getString(string.live_is_close_need_open),
                                mConfirm = StringUtils.getString(string.go_to_settings),
                                mCanal = StringUtils.getString(string.directly_open),
                                onConfirmCallback = {
                                    Router.builder(RoutePath.SET_ACTIVITY).navigation(requireContext())
                                },
                                onCanalCallback = {
                                    mViewModel.settingModify(UserConst.UserSetting.LIVE_MODULE_SWITFCH, AppConst.YES)
                                    LiveUtils.toSpectator(it.anchorId).navigation(requireContext())
                                }
                            )
                        } else {
                            LiveUtils.toSpectator(it.anchorId).navigation(requireContext())
                        }
                    }
                }


            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
    }

    private fun initListener() {
        ViewUtils.registerTouchDown(mBinding.vShade) {
            mOnSetStateNormal?.invoke()
        }
        mBinding.recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                mScrollState = newState
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    getSayHiMessage()
                }
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                val position = mBinding.recycler.getLastPosition() ?: 0
                if (mIsPullLoadEnable && position >= mAdapter.itemCount - 2
                    && (mScrollState == RecyclerView.SCROLL_STATE_SETTLING || mScrollState == RecyclerView.SCROLL_STATE_DRAGGING)
                ) {
                    loadMore()
                }
            }
        })
        mAdapter.setOnItemChildClickListener { _, view, position ->
            val item = mAdapter.getItem(position)
            val topActivity = ViewUtils.getAliveTopActivity()
            when (view.id) {
                R.id.av_avatar -> {
                    if (LiveStateManager.isLiving() || !mNeedClickAvatar) return@setOnItemChildClickListener
                    if (!PartyUserStateUtil.isGoOtherRouter()) return@setOnItemChildClickListener
                    if (topActivity is PartyAnchorActivity) return@setOnItemChildClickListener
                    if (item.command != COMMAND_SYSTEM_MESSAGE && item.command != COMMAND_STRANGER_MESSAGE) {
                        if (item.sender != UserManager.getUser().userId) {
                            Router.builder(RoutePath.USER_SPACE_ACTIVITY)
                                .withInt("page", UserConst.From.SINGLE)
                                .withLong("userId", item.sender)
                                .navigation(requireActivity())
                        }
                    }
                }

                R.id.right_content, R.id.left_iv_pic -> {
                    if (BitwiseUtils.isBitwise(item.type, TYPE_MESSAGE_IMAGE)) {
                        PicturePreview.with(requireActivity())
                            .byView(view)
                            .setImageUrlList(arrayListOf(ImageUtils.imgPath(item.content)))
                            .apply {
                                mUser?.let {
                                    setUserInfo(mUser)
                                }
                            }
                            .go()
                    }
                }

                R.id.iv_state -> {
                    if (view.isSelected) {
                        mViewModel.sendRetry(requireContext(), item)
                    }
                }

                R.id.iv_banner, R.id.tv_footer -> {
                    if (LiveStateManager.isLiving()) return@setOnItemChildClickListener
                    if (!PartyUserStateUtil.isGoOtherRouter()) return@setOnItemChildClickListener
                    if (topActivity is PartyAnchorActivity) return@setOnItemChildClickListener

                    val text = when (view.id) {
                        R.id.iv_banner -> item.payloadBean?.router?.get("banner")
                        R.id.tv_footer -> item.payloadBean?.router?.get("footer")
                        else -> null
                    }

                    if (text != null) {
                        if (text.contains(RoutePath.SET_LIVE_IMAGE_ACTIVITY)) {
                            if (UserManager.getUser().coverPhoto?.hasAuditingCover == false) {
                                RouterUtils.routerGoto(text)
                            } else {
                                mViewModel.userCover()
                            }
                        } else {
                            RouterUtils.routerGoto(text)
                        }
                    }
                }

                R.id.ll_call_left, R.id.ll_call_right -> {
                    DebounceHelper.singleClick {
                        if (!LiveStateManager.isNone()) return@singleClick
                        if (!PartyUserStateUtil.isGoOtherRouter()) return@singleClick
                        if (topActivity is PartyAnchorActivity) return@singleClick
                        val item =
                            mAdapter.getItemOrNull(position) ?: return@singleClick
                        if (BitwiseUtils.isBitwise(item.type, TYPE_MESSAGE_CALL)) {
                            StartCallProxy.builder(this).startCall(
                                mViewModel,
                                UserConst.From.SINGLE,
                                UserConst.LastFrom.SINGLE,
                                LiveConst.SenderFrom.MANUAL,
                                item.otherId,
                            )
                        }
                    }
                }

                R.id.go_live_party, R.id.go_live_tv -> { //去派对
                    if (LiveStateManager.isLiving() || !mNeedClickAvatar) return@setOnItemChildClickListener
                    if (!PartyUserStateUtil.isGoOtherRouter()) return@setOnItemChildClickListener
                    if (topActivity is PartyAnchorActivity) return@setOnItemChildClickListener
                    if (BitwiseUtils.isBitwise(item.type, TYPE_MESSAGE_INVITATION_ROOM)) {
                        item.payloadBean?.run {
                            anchor?.userId?.let { userId ->
                                liveId?.let { liveId ->
                                    mViewModel.inviteJoinPrepare(userId, liveId, roomId)
                                }
                            }
                        }
                    }
                }
            }
        }
        mAdapter.setOnItemLongClickListener { _, _, position ->
            handleLongClick(position)
        }
    }

    private fun handleLongClick(position: Int): Boolean {
        val holder = mBinding.recycler.findViewHolderForAdapterPosition(position)
        val item = mAdapter.getItem(position)
        val content = item.content

        val builder = when (holder) {
            is MessageSystemTextItemHolder -> holder.builder
            is MessageTextItemHolder -> {
                if (!WebUtils.isSafeUrlContent(content)) {
                    return false
                }
                holder.builder
            }

            else -> return false
        }

        val copyMessage = StringUtils.getString(string.copy_message)
        val toBrowser = StringUtils.getString(string.to_browser)
        val deleteMessage = StringUtils.getString(string.delete_message)

        val strings = when (holder) {
            is MessageSystemTextItemHolder -> arrayOf(copyMessage, deleteMessage)
            is MessageTextItemHolder -> arrayOf(copyMessage, toBrowser)
            else -> emptyArray()
        }

        builder.asAttachList(strings, null) { _, text ->
            when (text) {
                copyMessage -> {
                    ViewUtils.getAliveTopActivity()?.also {
                        SystemUtils.copyToClipboard(it, content)
                    }
                }

                toBrowser -> {
                    RouterUtils.routerGoto(content)
                }

                deleteMessage -> {
                    val otherId = if (item.sender == UserManager.getUser().userId) {
                        item.recipient
                    } else {
                        item.sender
                    }

                    mViewModel.deleteMessage(item, otherId)
                    mAdapter.removeAt(position)
                }
            }
        }.show()

        return true
    }

    /**
     * 当滑动停止时，获取当前屏幕展示的列表   判断是否存在打招呼消息   并且判断是否已读
     */
    private fun getSayHiMessage() {
        val wrapper = mBinding.recycler.getDisplayPosition(mAdapter.data) ?: return
        val list = mAdapter.data.subList(wrapper.firstPosition, wrapper.lastPosition)
        val listGreetPushMessageFlag = MessageEntityUtils.filterListGreetPushMessageFlag(list)
        if (listGreetPushMessageFlag.isEmpty()) return
        //获取到未读的打招呼消息
        mViewModel.messageRead(listGreetPushMessageFlag)
        //请求后修改当前展示列表的数据  防止重复请求
        listGreetPushMessageFlag.forEach { message ->
            val indexOf = mAdapter.data.indexOfFirst { it.msgId == message.msgId }
            if (indexOf != -1) {
                val item = mAdapter.getItemOrNull(indexOf) ?: return
                item.payloadBean?.let { payload ->
                    //修改本地标识
                    payload.flagGreetPushMessage = EXT_FLAG_PUSH_MESSAGE
                    val updatedPayload = JsonUtils.toJson(payload)

                    val updatedItem = item.copy(payload = updatedPayload)
                    mAdapter.data[indexOf] = updatedItem
                    mAdapter.notifyItemChanged(indexOf)
                }
            }
        }
    }

    private fun initDataFragment() {
        mViewModel.getMoreData(mOtherId, null)

        //清除与该用户的未读数
        mViewModel.clearUnreadCount(mOtherId)
    }

    private fun loadMore() {
        if (mIsLoading) {
            return
        }

        val message = if (mAdapter.data.isEmpty()) {
            null
        } else {
            mAdapter.getItem(mAdapter.itemCount - 1)
        }

        mViewModel.getMoreData(mOtherId, message?.timestamp)

        mIsLoading = true
    }

    //展示最新的一条
    fun scrollToBottom() {
        if (!isCreated()) {
            return
        }
        mBinding.recycler.scrollToPosition(0)
    }

    fun isToBottom(): Boolean {
        if (!isCreated()) {
            return false
        }
        return mScrollState == RecyclerView.SCROLL_STATE_IDLE && mBinding.recycler.getFirstPosition() == 0
    }

    /**
     * 设置是否完善信息
     */
    fun setCompInfo(ws: Boolean) {
        if (!ws) {
            if (mConcatAdapter?.adapters?.size == 1) {
                mConcatAdapter?.addAdapter(1, mHeadAdapter)
                mConcatAdapter?.notifyDataSetChanged()
            }
        } else {
            if (mConcatAdapter?.adapters?.size == 2) {
                mConcatAdapter?.removeAdapter(mHeadAdapter)
                mConcatAdapter?.notifyDataSetChanged()
            }
        }
    }

    fun setAvatar(avatar: String?, avatarFrame: String?, chatBubble: String?) {
        if (!isCreated()) {
            return
        }
        mAdapter.setDecorationData(avatar, avatarFrame, chatBubble)
    }

    fun setInfoOtherResp(user: InfoOtherResp?) {
        this.mUser = user
        user?.let {
            mAdapter.setRichs(it.account.richs)
        }
    }

    fun showFadingEdge() {
        if (!isCreated()) {
            return
        }

        mBinding.recycler.setTopFadingEdge(true)
    }

    fun setOnSetStateNormal(l: () -> Unit) {
        this.mOnSetStateNormal = l
    }

    fun getPushDetailId(): Long? {
        if (!isCreated()) {
            return null
        }
        return mGreetMessage?.pushDetailId
    }
}